<template>
  <div class="home-bg sidebar-layout">
    <div class="sidebar">
      <el-card class="sidebar-card">
        <div class="sidebar-title">
          <el-icon><Connection /></el-icon>
          <span>数据源信息</span>
        </div>
        <el-form :model="dsForm" label-width="90px" class="sidebar-form vertical-form">
          <el-form-item label="数据库类型">
            <el-select v-model="dsForm.dbType" placeholder="请选择">
              <el-option label="MySQL" value="mysql" />
              <el-option label="Oracle" value="oracle" />
              <el-option label="PostgreSQL" value="postgresql" />
              <el-option label="SQL Server" value="sqlserver" />
              <el-option label="SQLite" value="sqlite" />
              <el-option label="MariaDB" value="mariadb" />
              <el-option label="DB2" value="db2" />
              <el-option label="Sybase" value="sybase" />
              <el-option label="ClickHouse" value="clickhouse" />
              <el-option label="H2" value="h2" />
              <el-option label="Firebird" value="firebird" />
              <el-option label="Kingbase" value="kingbase" />
              <el-option label="达梦 DM" value="dm" />
              <el-option label="人大金仓 KingbaseES" value="kingbasees" />
            </el-select>
          </el-form-item>
          <el-form-item label="地址">
            <el-input v-model="dsForm.host" placeholder="如：localhost" clearable />
          </el-form-item>
          <el-form-item label="端口">
            <el-input v-model="dsForm.port" placeholder="自动填充默认端口，可修改" clearable />
          </el-form-item>
          <el-form-item label="库名">
            <el-input v-model="dsForm.dbName" placeholder="如：testdb" clearable />
          </el-form-item>
          <el-form-item label="用户名">
            <el-input v-model="dsForm.username" clearable />
          </el-form-item>
          <el-form-item label="密码">
            <el-input
              v-model="dsForm.password"
              :type="showPassword ? 'text' : 'password'"
              clearable
              autocomplete="off"
            >
              <template #suffix>
                <el-icon @click="showPassword = !showPassword" style="cursor:pointer;">
                  <component :is="showPassword ? Hide : View" />
                </el-icon>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="loadTables" :loading="loading" icon="Search">加载表</el-button>
          </el-form-item>
        </el-form>
      </el-card>
    </div>
    <div class="main-content">
      <el-card class="section-card param-card">
        <div class="section-inner">
          <div class="section-title">
            <el-icon><EditPen /></el-icon>
            <span>生成参数</span>
          </div>
          <el-form :model="genForm" label-width="90px" class="section-form vertical-form">
            <el-form-item label="作者">
              <el-input v-model="genForm.author" placeholder="请输入作者名" clearable />
            </el-form-item>
            <el-form-item label="包名">
              <el-input v-model="genForm.packageName" placeholder="如：com.example.demo" clearable />
            </el-form-item>
            <el-form-item label="输出路径">
              <el-input v-model="genForm.outputPath" placeholder="如：D:/output" clearable />
            </el-form-item>
          </el-form>
        </div>
      </el-card>
      <el-card class="section-card table-card">
        <div class="section-title table-title-row" style="display: flex; align-items: center;">
          <el-icon><List /></el-icon>
          <span>选择数据表</span>
        </div>
        <div class="table-filter-row">
          <el-input
            v-model="filterTableName"
            placeholder="请输入表名进行筛选"
            clearable
            prefix-icon="Search"
            size="large"
            class="table-filter-input"
          />
          <el-button type="success" :disabled="selected.length === 0" @click="generateCode" :loading="genLoading" icon="MagicStick" size="large" class="table-filter-btn">
            生成代码
          </el-button>
        </div>
        <div class="table-scroll-x full-width-table">
          <el-table
            :data="pagedTables"
            @selection-change="onSelect"
            border
            stripe
            style="width: 100%; min-width: 600px;"
            :row-key="row => row.name"
            ref="tableRef"
            empty-text="暂无数据，请先加载数据表"
            table-layout="auto"
          >
            <el-table-column type="selection" width="55" fixed />
            <el-table-column prop="name" label="表名" min-width="140" />
            <el-table-column prop="description" label="表描述" min-width="200" />
            <el-table-column prop="engine" label="引擎" min-width="90" />
            <el-table-column prop="autoIncrement" label="自增" min-width="80">
              <template #default="scope">
                <span v-if="scope.row.autoIncrement">{{ scope.row.autoIncrement === true || scope.row.autoIncrement === 'true' ? '是' : scope.row.autoIncrement }}</span>
                <span v-else>否</span>
              </template>
            </el-table-column>
            <el-table-column prop="charset" label="字符集" min-width="100" />
            <el-table-column prop="collation" label="排序规则" min-width="160" />
            <el-table-column label="操作" width="90" fixed="right">
              <template #default="scope">
                <el-button size="small" @click="previewTableStructure(scope.row)" type="primary" link>预览</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <div v-if="tables.length" class="table-pagination">
          <el-pagination
            background
            layout="prev, pager, next, jumper, ->, total"
            :total="filterTableName ? tables.filter(t => t.name && t.name.toLowerCase().includes(filterTableName.toLowerCase())).length : tables.length"
            :page-size="pageSize"
            :current-page.sync="currentPage"
            @current-change="onPageChange"
            small
          />
        </div>
      </el-card>
      <!-- 表结构预览弹窗 -->
      <el-dialog
        v-model="previewDialogVisible"
        width="min(98vw, 700px)"
        :close-on-click-modal="false"
        class="preview-dialog beautified-dialog"
        :destroy-on-close="true"
      >
        <template #title>
          <span style="display:flex;align-items:center;font-weight:600;font-size:18px;color:#409eff;">
            <i class="el-icon-View" style="margin-right:8px;font-size:20px;"></i>
            表结构预览：{{ previewTable?.name || '' }}
          </span>
        </template>
        <div class="preview-table-wrap beautified-preview-table">
          <el-table
            :data="previewColumns"
            border
            stripe
            style="width: 100%; min-height:200px;"
            size="large"
            header-cell-class-name="preview-table-header"
            :cell-style="{ textAlign: 'center' }"
            :header-cell-style="{ background: '#f5f7fa', fontWeight: 'bold', fontSize: '16px' }"
            :row-class-name="row => row.primaryKey ? 'row-primary' : ''"
            height="100%"
          >
            <el-table-column prop="name" label="字段名" min-width="120" align="center" show-overflow-tooltip />
            <el-table-column prop="type" label="类型" min-width="120" align="center" show-overflow-tooltip>
              <template #default="scope">
                <el-tag type="info" effect="plain">{{ scope.row.type }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="primaryKey" label="主键" min-width="70" align="center">
              <template #default="scope">
                <el-tag v-if="scope.row.primaryKey" type="success" effect="dark">是</el-tag>
                <span v-else>否</span>
              </template>
            </el-table-column>
            <el-table-column prop="nullable" label="可为空" min-width="80" align="center">
              <template #default="scope">
                <el-tag :type="scope.row.nullable ? 'info' : 'danger'" effect="plain">
                  {{ scope.row.nullable ? '是' : '否' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="autoIncrement" label="自增" min-width="70" align="center">
              <template #default="scope">
                <el-tag v-if="scope.row.autoIncrement" type="warning" effect="plain">是</el-tag>
                <span v-else>否</span>
              </template>
            </el-table-column>
            <el-table-column prop="comment" label="字段注释" min-width="180" align="left" show-overflow-tooltip />
          </el-table>
        </div>
        <template #footer>
          <div class="preview-footer">
            <el-button @click="previewDialogVisible = false" type="primary" size="large" round>关闭</el-button>
          </div>
        </template>
      </el-dialog>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, nextTick, watch, h } from 'vue';
import { ElMessage } from 'element-plus';
import axios from 'axios';
import { Connection, List, EditPen, MagicStick, View, Hide } from '@element-plus/icons-vue';

const defaultPorts = {
  mysql: '3306',
  oracle: '1521',
  postgresql: '5432',
  sqlserver: '1433',
  sqlite: '',
  mariadb: '3306',
  db2: '50000',
  sybase: '5000',
  clickhouse: '8123',
  h2: '9092',
  firebird: '3050',
  kingbase: '54321',
  dm: '5236',
  kingbasees: '54321'
};

const dsForm = ref({
  dbType: 'mysql',
  host: '',
  port: defaultPorts['mysql'],
  dbName: '',
  username: '',
  password: ''
});

watch(() => dsForm.value.dbType, (newType) => {
  dsForm.value.port = defaultPorts[newType] || '';
});

const showPassword = ref(false);
const tables = ref([]); // [{name, comment, description, createTime, updateTime}]
const selected = ref([]);
const loading = ref(false);
const genLoading = ref(false);
const currentPage = ref(1);
const pageSize = 10;
const tableRef = ref();

const previewDialogVisible = ref(false);
const previewTable = ref(null);
const previewColumns = ref([]); // [{name, type, primaryKey, nullable, comment}]

const genForm = ref({
  author: '',
  packageName: '',
  outputPath: ''
});

const filterTableName = ref('');

const pagedTables = computed(() => {
  let filtered = tables.value;
  if (filterTableName.value) {
    filtered = filtered.filter(t => t.name && t.name.toLowerCase().includes(filterTableName.value.toLowerCase()));
  }
  const start = (currentPage.value - 1) * pageSize;
  return filtered.slice(start, start + pageSize);
});

function buildJdbcUrl() {
  if (dsForm.value.dbType === 'mysql') {
    return `jdbc:mysql://${dsForm.value.host}:${dsForm.value.port}/${dsForm.value.dbName}`;
  } else if (dsForm.value.dbType === 'oracle') {
    return `jdbc:oracle:thin:@${dsForm.value.host}:${dsForm.value.port}:${dsForm.value.dbName}`;
  }
  return '';
}

const loadTables = async () => {
  loading.value = true;
  try {
    const req = {
      url: buildJdbcUrl(),
      username: dsForm.value.username,
      password: dsForm.value.password
    };
    const res = await axios.post('/api/datasource/tables', req);
    tables.value = res.data;
    currentPage.value = 1;
    selected.value = [];
    await nextTick();
    if (tableRef.value) tableRef.value.clearSelection();
    ElMessage.success('加载成功');
  } catch (e) {
    ElMessage.error('加载失败');
    tables.value = [];
    selected.value = [];
  } finally {
    loading.value = false;
  }
};

const onSelect = (rows) => {
  selected.value = rows;
};

const onPageChange = (page) => {
  currentPage.value = page;
  nextTick(() => {
    // 保持已选项在分页切换后依然高亮
    if (tableRef.value && selected.value.length) {
      pagedTables.value.forEach(row => {
        if (selected.value.find(sel => sel.name === row.name)) {
          tableRef.value.toggleRowSelection(row, true);
        }
      });
    }
  });
};

const generateCode = async () => {
  genLoading.value = true;
  try {
    const req = {
      ...genForm.value,
      tables: selected.value.map(t => t.name),
      url: buildJdbcUrl(),
      username: dsForm.value.username,
      password: dsForm.value.password
    };
    const res = await axios.post('/api/codegen/generate', req);
    if (res.data.success) {
      ElMessage.success(res.data.message || '生成成功');
    } else {
      ElMessage.error(res.data.message || '生成失败');
    }
  } catch (e) {
    ElMessage.error('生成失败');
  } finally {
    genLoading.value = false;
  }
};

const previewTableStructure = async (table) => {
  previewTable.value = table;
  previewDialogVisible.value = true;
  previewColumns.value = [];
  try {
    const req = {
      url: buildJdbcUrl(),
      username: dsForm.value.username,
      password: dsForm.value.password,
      tableName: table.name
    };
    const res = await axios.post('/api/datasource/columns', req);
    previewColumns.value = res.data;
  } catch (e) {
    ElMessage.error('获取表结构失败');
  }
};
</script>

<style scoped>
.home-bg.sidebar-layout {
  min-height: 100vh;
  width: 100vw;
  background: linear-gradient(135deg, #f0f4ff 0%, #e9f7ef 100%);
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
}
.sidebar {
  width: 30vw;
  min-width: 260px;
  max-width: 40vw;
  background: #f7f8fa;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  box-sizing: border-box;
  padding: 0;
  border-right: 1.5px solid #e4e7ed;
  overflow: visible;
}
.sidebar-card {
  width: 100%;
  height: 100%;
  border-radius: 0;
  box-shadow: none;
  border: none;
  background: transparent;
  padding: 32px 18px 18px 18px;
  box-sizing: border-box;
  overflow: hidden;
}
.sidebar-title {
  display: flex;
  align-items: center;
  font-size: 19px;
  font-weight: 600;
  margin-bottom: 18px;
  color: #409eff;
}
.sidebar-title .el-icon {
  margin-right: 8px;
  font-size: 22px;
}
.sidebar-form {
  margin-bottom: 0;
}
.main-content {
  width: 70vw;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 32px 32px 32px 32px;
  box-sizing: border-box;
  max-width: 100vw;
  overflow: visible;
}
.param-card,
.section-card.table-card,
.section-card,
.section-inner,
.section-form,
.vertical-form,
.table-scroll-x {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: auto;
}
.vertical-form .el-form-item {
  min-width: 0;
  flex: 1 1 0%;
}
.vertical-form .el-form-item__content {
  min-width: 0;
  flex: 1 1 0%;
  width: 100%;
}
.vertical-form .el-input,
.vertical-form .el-select {
  min-width: 0;
  flex: 1 1 0%;
  width: 100%;
  max-width: unset;
}
.section-title {
  display: flex;
  align-items: center;
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 18px;
  color: #409eff;
}
.section-title .el-icon {
  margin-right: 8px;
  font-size: 22px;
}
.section-form {
  margin-bottom: 0;
}
.text-right {
  text-align: right;
}
.table-empty {
  color: #bbb;
  text-align: center;
  padding: 30px 0 10px 0;
  font-size: 15px;
}
.table-pagination {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  min-width: 0;
  justify-content: flex-end;
  align-items: center;
  margin: 18px 0 0 0;
  text-align: right;
  gap: 4px;
}
.mt-3 {
  margin-top: 20px;
}
.section-inner {
  width: 100%;
  display: flex;
  flex-direction: column;
}
.vertical-form {
  width: 100%;
}
.vertical-form .el-form-item {
  margin-bottom: 22px;
}
.vertical-form .el-form-item__label {
  font-weight: 500;
  color: #333;
  font-size: 15px;
}
.table-scroll-x {
  width: 100%;
  min-width: 0;
  overflow-x: auto;
  padding-bottom: 2px;
  margin: 0;
}
body, html {
  /* overflow: hidden !important; */
}
@media (max-width: 1200px) {
  .sidebar {
    width: 38vw;
    min-width: 180px;
    max-width: 50vw;
  }
  .main-content {
    width: 62vw;
    padding: 18px 8px 18px 8px;
  }
}
@media (max-width: 900px) {
  .home-bg.sidebar-layout {
    flex-direction: column;
    min-height: unset;
    height: auto;
  }
  .sidebar {
    width: 100vw;
    min-width: 0;
    max-width: 100vw;
    height: auto;
    border-right: none;
    border-bottom: 1.5px solid #e4e7ed;
    padding: 0 0 12px 0;
  }
  .main-content {
    width: 100vw;
    min-width: 0;
    height: auto;
    padding: 12px 2vw 12px 2vw;
    gap: 12px;
    max-width: 100vw;
    overflow: visible;
  }
  .section-card.table-card {
    min-width: 0;
    width: 100%;
    padding: 0 0 12px 0;
  }
  .table-title-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
  .table-title-row .el-button {
    width: 100%;
    margin-left: 0 !important;
  }
  .param-card,
  .section-card.table-card,
  .section-card,
  .section-inner,
  .section-form,
  .vertical-form,
  .table-scroll-x {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    padding-left: 2vw;
    padding-right: 2vw;
    overflow: auto;
  }
  .table-scroll-x {
    overflow-x: auto;
  }
  .vertical-form .el-form-item__content {
    width: 100vw;
  }
  .table-pagination {
    padding-left: 2vw;
    padding-right: 2vw;
    margin: 10px 0 0 0;
  }
  .section-card.table-card .el-input {
    width: 100% !important;
    max-width: 100vw;
    margin-bottom: 10px;
  }
}
@media (max-width: 600px) {
  .main-content {
    padding: 4px 1vw 4px 1vw;
    gap: 6px;
    max-width: 100vw;
    overflow: visible;
  }
  .section-card {
    padding: 4px 2px 4px 2px;
  }
  .section-title {
    font-size: 15px;
  }
  .sidebar-card {
    padding: 12px 4px 8px 4px;
  }
  .vertical-form .el-form-item__label {
    font-size: 12px;
  }
  .vertical-form .el-input,
  .vertical-form .el-select {
    font-size: 13px;
    padding: 2px 4px;
  }
  .el-table th, .el-table td {
    font-size: 12px;
    padding: 4px 2px;
  }
  .beautified-preview-table .el-dialog {
    min-width: unset !important;
    width: 98vw !important;
    max-width: 100vw !important;
    padding: 0;
  }
  .section-form,
  .section-card,
  .param-card {
    padding-left: 1vw;
    padding-right: 1vw;
    overflow: auto;
  }
  .table-scroll-x {
    overflow-x: auto;
  }
  .table-pagination {
    padding-left: 1vw;
    padding-right: 1vw;
    margin: 6px 0 0 0;
  }
}
.full-width-table {
  width: 100%;
  min-width: 0;
  overflow-x: auto;
}
.el-card,
.section-card,
.param-card,
.el-card__body {
  overflow: visible !important;
}
.beautified-dialog >>> .el-dialog__body {
  padding: 32px 32px 18px 32px;
  background: #f8fafc;
}
.beautified-dialog >>> .el-dialog {
  border-radius: 14px;
  box-shadow: 0 4px 32px 0 rgba(0,0,0,0.10);
}
.beautified-preview-table {
  background: #fff;
  border-radius: 10px;
  padding: 0;
  margin-bottom: 0;
}
.beautified-preview-table .el-table th {
  font-weight: bold;
  background: #f5f7fa !important;
  font-size: 16px;
}
.beautified-preview-table .el-table td {
  font-size: 15px;
  padding: 10px 6px;
}
.beautified-preview-table .el-table__body tr:hover > td {
  background: #f0f7ff !important;
}
.beautified-preview-table .el-table__header th {
  border-bottom: 1.5px solid #e4e7ed;
}
.beautified-preview-table .el-table__body td {
  border-bottom: 1px solid #f0f0f0;
}
.beautified-dialog >>> .el-dialog__footer {
  background: #f8fafc;
  border-top: 1px solid #f0f0f0;
  padding: 18px 32px 18px 32px;
}
.beautified-dialog .preview-footer {
  text-align: center;
  margin-top: 0;
}
.preview-table-header {
  background: #f5f7fa !important;
  font-weight: bold;
  font-size: 16px;
}
.row-primary {
  background: #e6f7ff !important;
}
.beautified-preview-table .el-tag {
  margin: 0 2px;
  font-size: 13px;
  border-radius: 6px;
}
.table-title-row {
  margin-bottom: 18px;
}
@media (max-width: 700px) {
  .beautified-dialog >>> .el-dialog {
    width: 98vw !important;
    min-width: unset !important;
    max-width: 100vw !important;
    padding: 0;
  }
}
.preview-table-wrap {
  max-height: 60vh;
  overflow-y: auto;
}
@media (max-width: 900px) {
  .preview-table-wrap {
    max-height: 50vh;
  }
}
@media (max-width: 600px) {
  .preview-table-wrap {
    max-height: 40vh;
  }
}
.table-filter-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.table-filter-input {
  flex: 1 1 0%;
  min-width: 0;
}
.table-filter-btn {
  margin-left: 12px;
  white-space: nowrap;
}
@media (max-width: 900px) {
  .table-filter-row {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .table-filter-input,
  .table-filter-btn {
    width: 100% !important;
    margin-left: 0 !important;
  }
}
</style> 